package net

import (
	"dgo/MyProj/PrjConf"
	"dgo/MyProj/PrjHttpUtils"
	"dgo/goutils/dnet"
	"dgo/goutils/utils"
	"fmt"
	"gitee.com/ymofen/supervalue"
	"strings"
)

type ProjProxyTcpPlugin struct {
	PlgBase
	proxy   *dnet.ProxyTcp
	logflag int
}

func (this *ProjProxyTcpPlugin) Close() error {

	return nil
}

func (this *ProjProxyTcpPlugin) OnHttpStatus(rec *PlgHttpRec) (rval interface{}, errcode int, err error) {
	itype := rec.QryAsInt("type", 0)
	if itype == 1 {
		json := wrapper.NewSVArray()
		searchval := rec.QryAsString("searchval", "")
		this.proxy.Sessions.ListRangeV2(func(key, value interface{}) bool {
			val := value.(*dnet.ProxyTcpRec)
			ret := true
			if len(searchval) > 0 && ret {
				ret = strings.Contains(val.FrontendAddr, searchval) || strings.Contains(val.BackendAddr, searchval)
			}
			return ret
		}, func(k0, v0, k1, v1 interface{}) bool {
			req0 := v0.(*dnet.ProxyTcpRec)
			req1 := v1.(*dnet.ProxyTcpRec)
			return req0.StartT.Before(req1.StartT)
		}, func(key, val interface{}) bool {
			req := val.(*dnet.ProxyTcpRec)
			itm := json.AppendObject()
			itm.SetKeyValue("start", utils.DateTimeString2(req.StartT))
			itm.SetKeyValue("from", fmt.Sprintf("[%s]<->[%s]", req.BackendAddr, req.FrontendAddr))
			itm.SetKeyValue("backend-info", req.GetBackendInfo())
			itm.SetKeyValue("frontend-info", req.GetFrontendInfo())
			return true
		})
		PrjHttpUtils.JSON2TableEx(rec.RespW, "", json.AsJSONString(false), nil)
		//} else if itype == 2 {
		//	rec.ResponseSyncListNEx(this.msglist)
		//} else if itype == 3 {
		//	this.msglist.Clear()
		//	rec.ResponseJSONValues("code", 0)
	} else {
		var sb utils.BytesBuilder
		PrjHttpUtils.AppendIndexBody(&sb, "list", "status?type=1&searchval=")
		//PrjHttpUtils.AppendIndexBody(&sb, "msglist", "status?type=2&n=100&searchval=")
		//PrjHttpUtils.AppendIndexBody(&sb, "msg-clear", "status?type=3")
		PrjHttpUtils.ResponseBodyHtml(rec.RespW, sb.String())
	}

	return
}

/*
*

	{
	  "id": "proxy",
	  "type": "comm.proxy.tcp",
	  "conf": {
	    "frontend":":15100",
	    "backend":"139.199.181.47:6973",
	    "logflag":0,
	  }
	}
*/
func (this *ProjProxyTcpPlugin) ReloadConf(conf *wrapper.SuperValue) error {
	if this.proxy == nil {
		this.proxy = dnet.NewProxyTcp()
		this.proxy.OnListenSucc = func() {
			if this.logflag == 1 {
				utils.Log.InfoTypef(this.PlugId, "[%s]侦听成功!", this.proxy.GetFrontendAddr())
			}
		}
		this.proxy.OnFrontendRecv = func(sender *dnet.ProxyTcpRec, buf []byte) {
			if this.logflag == 1 {
				utils.Log.InfoTypef(this.PlugId, "[%s]->[%s]:%s", sender.Frontend_conn.RemoteAddr(), sender.Backend_conn.RemoteAddr(), utils.BufToHexStr(buf, 0, ""))
			}
		}
		this.proxy.OnBackendRecv = func(sender *dnet.ProxyTcpRec, buf []byte) {
			if this.logflag == 1 {
				utils.Log.InfoTypef(this.PlugId, "[%s]<-[%s]:%s", sender.Frontend_conn.RemoteAddr(), sender.Backend_conn.RemoteAddr(), utils.BufToHexStr(buf, 0, ""))
			}
		}
	}

	conf.CheckExistsIntFunc("logflag", func(val int64) {
		this.logflag = int(val)
	})

	conf.CheckExistsIntFunc("frontend-maxonline", func(val int64) {
		//this.tcpsvr.SetMaxOnline(uint32(val))
	})

	conf.CheckExistsIntFunc("frontend-timeout-secs", func(val int64) {
		//if val > 0 {
		//	this.tcpsvr.ConfigCheckTimeoutInterval(5)
		//}
		//this.tcpsvr.ConfigKickTimeOut(int(val))
	})

	conf.CheckExistsStrFunc("backend", func(val string) {
		this.proxy.SetBackendAddr(val)
	})

	conf.CheckStrFunc("frontend", func(strv string) {
		this.proxy.SetFrontendAddr(strv)
		if !this.proxy.GetActive() {
			utils.GoFunc2(this.proxy.Open)
		}
	})

	this.ReloadStatusOConf(conf, func() {
		this.SendStatusFunc(func(json *wrapper.SuperValue) {
			json.SetKeyValues("plugid", this.PlugId, "uuid", PrjConf.APP_UUID, "online", this.proxy.OnlineCnt)
		})
	}, func() {
		//utils.Monitor.AddMonitorRec(fmt.Sprintf("plugin_%d_recv", this.PlugDNA), &this.recvMonitor)
	}, func() {
		//utils.Monitor.RemoveMonitorRec(fmt.Sprintf("plugin_%d_recv", this.PlugDNA))
	})

	return nil
}

func (this *ProjProxyTcpPlugin) OnObjectNotify(sender interface{}, notifytype int, data interface{}) (rval interface{}, err error) {
	if notifytype == utils.NOTIFY_TYPE_SETCONF {
		if conf, ok := data.(*wrapper.SuperValue); ok {
			err = this.ReloadConf(conf)
		} else {
			err = fmt.Errorf("非法的JSON配置")
		}
	} else if notifytype == utils.NOTIFY_TYPE_RELEASE {
	}
	return
}

func CreateProjProxyTcpPluginFunc(args ...interface{}) (rval interface{}, err error) {
	obj := &ProjProxyTcpPlugin{}
	if len(args) > 0 {
		if str, ok := args[0].(string); ok {
			obj.PlugId = str
		}
	}
	rval = obj
	return
}
